package com.yaodian100.ec.creditcard.entity;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.xml.bind.annotation.XmlTransient;

import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;

import com.yaodian100.core.common.entity.BaseEntity;

@Entity(name = "creditcard")
@Table(name = "EC_CREDITCARD_CAMPAIGN")
public class Creditcard extends BaseEntity {

	private static final long serialVersionUID = 7119724835708884260L;

	public enum Range {
		// 整張訂單生效
		Order("全站"),
		// 以"," 分隔活動目錄, 以加入購物車的 z 為準.
		Category("分類"),
		// 活動商品代碼. 限放一個
		Product("商品");
		String desc;

		Range(String desc) {
			this.desc = desc;
		}

		public String getDesc() {
			return desc;
		}

		public String getCode() {
			return name();
		}
	}
	
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO, generator = "seq_ec_creditcard_campaign")
	@SequenceGenerator(name = "seq_ec_creditcard_campaign", sequenceName = "SEQ_EC_CREDITCARD_CAMPAIGN")
	@Column(name = "ID")
	private long id;
	
	/**
	 * 活动名称 Campaign Name
	 */
	@Column(name = "CAMPAIGN_NAME", length = 100, nullable = false)
	private String campaignName;
	
	/**
	 * 活动说明 Campaign Description
	 */
	@Column(name = "CAMPAIGN_DESC", length = 500)
	private String campaignDesc;
	
	/**
	 * 活动辦法 Campaign Detail
	 */
	@Column(name = "CAMPAIGN_DEATIL", length = 1000)
	private String campaignDetail;
	
	/**
	 * 活动范围
	 */
	@Column(name = "CAMPAIGN_RANGE", columnDefinition = "numeric(2)", nullable = false)
	private Range range = Range.Order;
	
	// CAMPAIGN_RANGN_DET
	@Column(name = "CAMPAIGN_RANGN_DET", length = 800)
	private String campaignRangeDet;
	
	/**
	 * 活动开始时间 Start Date
	 */
	@Column(name = "START_DATE", nullable = false)
	@Temporal(TemporalType.TIMESTAMP)
	private Date startDate;
	
	/**
	 * 活动结束时间 End Date
	 */
	@Column(name = "END_DATE", nullable = false)
	@Temporal(TemporalType.TIMESTAMP)
	private Date endDate;
	
	/**
	 * 放置信用卡公告網頁（预留）
	 */
	@Column(name = "URL", length = 200)
	private String campaignUrl;
	
	/**
	 * 若該欄位有值, 則結帳時, 必須要有該 cookie 值, 才符合活動要求
	 */
	@Column(name = "COOKIE", length = 100)
	private String cookie;
	
	/**
	 * DOMAIN
	 */
	@Column(name = "DOMAIN", length = 100, nullable = false)
	private String domain;
	
	/**
	 * 该活动是否启用, Y: 是； N: 否
	 */
	@Column(name = "IS_ENABLE", nullable = false)
	private boolean enable = false;
	
	/**
	 * 备注栏位
	 */
	@Column(name = "MEMO", length = 1000)
	private String memo;
	
	/**
	 * 预算归属, 維護於選單 Menu 'Budget'（预留）
	 */
	@Column(name = "BUDGET", length = 2)
	private String budget = "A";
	
	/**
	 * 删除标记 , Y: 是； N: 否
	 */
	@Column(name = "IS_DELETE", nullable = false)
	private boolean delete = false;
	/*
	@Cascade({ CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN })
	@OnDelete(action = OnDeleteAction.CASCADE)
	*/
	@OneToMany(targetEntity = CreditcardDetail.class, mappedBy = "creditcard", fetch = FetchType.EAGER)
	@OrderBy("id asc")
	private List<CreditcardDetail> cardDetails;
	
	/**
	 * 取得信用卡最大分期期数之集合
	 */
	@Transient
	private List<String> periodUnion;
	
	/**
	 * structure: {bank_id: {period: fee}}
	 */
	@Transient
	private Map<String, Map<String, Float>> bankFeeMap;

	public Map<String, Map<String, Float>> getBankFeeMap() {
		
		if(cardDetails != null && cardDetails.size() > 0) {
			bankFeeMap = new HashMap<String, Map<String,Float>>();
			for(CreditcardDetail dtl : cardDetails) {
				String bankId = dtl.getSetting().getId() + "";
				Map<String,Float> periodFees = dtl.getPeriodFees();
				bankFeeMap.put(bankId, periodFees);
			}
		}
		
		return bankFeeMap;
	}

	public void setBankFeeMap(Map<String, Map<String, Float>> bankFeeMap) {
		this.bankFeeMap = bankFeeMap;
	}

	public List<String> getPeriodUnion() {
		
		if(cardDetails != null && cardDetails.size() > 0) {
			periodUnion = new ArrayList<String>();
			
			for(CreditcardDetail dtl : cardDetails) {
				List<String> periods = dtl.getPeriods();
				if(periodUnion.size() == 0) {
					periodUnion.addAll(periods);
				} else {
					for(String period : periods) {
						boolean isExist = false;
						for(String target : periodUnion) {
							if(target.equals(period)) {
								isExist = true;
								break;
							}
						}
						if(!isExist)
							periodUnion.add(period);
					}
				}
			}
			
			Collections.sort(periodUnion, new Comparator<String>() {
				@Override
				public int compare(String o1, String o2) {
					Integer i1 = new Integer(o1);
					Integer i2 = new Integer(o2);
					return i1.compareTo(i2);
				}
			});
		}
		
		return periodUnion;
	}

	@XmlTransient
	@Transient
	public List<String> getCookieArray() {
		List<String> cookieArray = new ArrayList<String>();
		if (StringUtils.isNotBlank(cookie)) {
			for (String s : StringUtils.split(cookie, ",")) {
				cookieArray.add(s);
			}
		}
		return cookieArray;
	}

	public void setCookieArray(List<String> cookieArray) {
		if (cookieArray != null) {
			cookie = StringUtils.join(cookieArray, ",");
		}
	}

	public void setPeriodUnion(List<String> periodUnion) {
		this.periodUnion = periodUnion;
	}
	
	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getCampaignName() {
		return campaignName;
	}

	public void setCampaignName(String campaignName) {
		this.campaignName = campaignName;
	}

	public String getCampaignDesc() {
		return campaignDesc;
	}

	public void setCampaignDesc(String campaignDesc) {
		this.campaignDesc = campaignDesc;
	}

	public String getCampaignDetail() {
		return campaignDetail;
	}

	public void setCampaignDetail(String campaignDetail) {
		this.campaignDetail = campaignDetail;
	}

	public Range getRange() {
		return range;
	}

	public void setRange(Range range) {
		this.range = range;
	}

	public String getCampaignRangeDet() {
		return campaignRangeDet;
	}

	public void setCampaignRangeDet(String campaignRangeDet) {
		this.campaignRangeDet = campaignRangeDet;
	}

	public Date getStartDate() {
		return startDate;
	}

	public void setStartDate(Date startDate) {
		this.startDate = startDate;
	}

	public Date getEndDate() {
		return endDate;
	}

	public void setEndDate(Date endDate) {
		this.endDate = endDate;
	}

	public String getCampaignUrl() {
		return campaignUrl;
	}

	public void setCampaignUrl(String campaignUrl) {
		this.campaignUrl = campaignUrl;
	}

	public String getCookie() {
		return cookie;
	}

	public void setCookie(String cookie) {
		this.cookie = cookie;
	}

	public String getDomain() {
		return domain;
	}

	public void setDomain(String domain) {
		this.domain = domain;
	}

	public boolean isEnable() {
		return enable;
	}

	public void setEnable(boolean enable) {
		this.enable = enable;
	}

	public String getMemo() {
		return memo;
	}

	public void setMemo(String memo) {
		this.memo = memo;
	}

	public String getBudget() {
		return budget;
	}

	public void setBudget(String budget) {
		this.budget = budget;
	}

	public boolean isDelete() {
		return delete;
	}

	public void setDelete(boolean delete) {
		this.delete = delete;
	}

	public List<CreditcardDetail> getCardDetails() {
		if(cardDetails == null)
			cardDetails = new ArrayList<CreditcardDetail>();
		
		return cardDetails;
	}

	public void setCardDetails(List<CreditcardDetail> cardDetails) {
		this.cardDetails = cardDetails;
	}
	
	public Creditcard addCardDetails(CreditcardDetail detail) {
		detail.setCreditcard(this);
		getCardDetails().add(detail);
		return this;
	}
	
	public Creditcard addCardDetails(int operation, CreditcardDetail detail) {
		detail.setCreditcard(this);
		getCardDetails().add(operation, detail);
		return this;
	}
}
